﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using IniParser;
using IniParser.Model;

namespace MolyMart.WithOPC
{
    public class Initializer
    {

        private List<OpcServerDefinition> _opcServerDefinitions ;
        private BlockingCollection<OpcServer> _quietQueue = new BlockingCollection<OpcServer>();
        private BlockingCollection<OpcServer> _activeQueue = new BlockingCollection<OpcServer>();
        private BlockingCollection<MessageItem> _messageQueue;
        private BlockingCollection<ServerValuesItem> _valuesQueue;
        private readonly int _workerOnServerThreads ;
        private readonly int _workOnValueThreads ;
       
        public Initializer(List<OpcServerDefinition> opcServerDefinitions,BlockingCollection<ServerValuesItem> valuesQueue, BlockingCollection<MessageItem> messageQueue, int workerOnServerThreads = 1, int workOnValueThreads =1)
        {
            _opcServerDefinitions = opcServerDefinitions;
            _valuesQueue = valuesQueue;
            _messageQueue = messageQueue;
            _workerOnServerThreads = workerOnServerThreads;
            _workOnValueThreads = workOnValueThreads;
        }

        public void Start()
        {
            List<OpcServer> opcServers = new List<OpcServer>();
            MakeOpcServers(_opcServerDefinitions,opcServers);
            InitQueues(opcServers,out _quietQueue,out _activeQueue);

            ConnectonWorker wos = new ConnectonWorker(_quietQueue, _activeQueue,_messageQueue);
            ValuesWorker wol = new ValuesWorker(_quietQueue, _activeQueue, _valuesQueue, _messageQueue);
            bool[] workerOnServerThreads = new bool[_workerOnServerThreads];
            bool[] workerOnValueThreads = new bool[_workOnValueThreads];
            foreach (bool b in workerOnServerThreads)
            {
                Thread serverThread = new Thread(wos.Run) {IsBackground = true};
                serverThread.Start();
            }
            foreach (bool b in workerOnValueThreads)
            {
                Thread valuesThread = new Thread(wol.Run) {IsBackground = true};
                valuesThread.Start();
            }
        }

        private void InitQueues(List<OpcServer> opcServerlList,out BlockingCollection<OpcServer> quietQueue,out BlockingCollection<OpcServer> activeQueue )
        {
            quietQueue = new BlockingCollection<OpcServer>(new ConcurrentQueue<OpcServer>(opcServerlList),byte.MaxValue);
            activeQueue = new BlockingCollection<OpcServer>(new ConcurrentQueue<OpcServer>(),byte.MaxValue);
        }

        private void MakeOpcServers(List<OpcServerDefinition> serverDefinitions, List<OpcServer> opcServers)
        {
            serverDefinitions.ForEach(i =>
            {
                OpcServer newOpcServer = new OpcServer();
                newOpcServer.OpcServerDefinition = i;
                newOpcServer.ServerState= ServerState.Initialized;
                opcServers.Add(newOpcServer);
            });
        }
    }
}
